<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="PMtfE" id="PMtfE"><span data-lake-id="u1342179d" id="u1342179d">典型回答</span></h1>
  <p data-lake-id="u15b06a06" id="u15b06a06"><span data-lake-id="u1d2a964e" id="u1d2a964e">限流和降级都是对系统的保护功能，一般用户在流量高峰时期，比如双十一大促。</span></p>
  <p data-lake-id="ub676cba6" id="ub676cba6"><br></p>
  <p data-lake-id="u05e92f11" id="u05e92f11"><span data-lake-id="ub0311ed0" id="ub0311ed0">降级是通过开关配置将某些不重要的业务功能屏蔽掉，以提高服务处理能力。在大促场景中经常会对某些服务进行降级处理，大促结束之后再进行复原。</span></p>
  <p data-lake-id="u951a74ab" id="u951a74ab"><span data-lake-id="ua9ed0b87" id="ua9ed0b87">​</span><br></p>
  <p data-lake-id="uc5aacb15" id="uc5aacb15"><strong><span data-lake-id="u4aad940a" id="u4aad940a">区别于熔断机制，降级一般并不是彻底功能不可用，而是用一种默认返回、异步执行、延迟处理等方式进行降低处理。</span></strong></p>
  <p data-lake-id="u293436d6" id="u293436d6"><strong><span data-lake-id="u7722855f" id="u7722855f">​</span></strong><br></p>
  <h1 data-lake-id="rCubj" id="rCubj"><span data-lake-id="u414a9e32" id="u414a9e32">扩展知识</span></h1>
  <p data-lake-id="u6b3b3032" id="u6b3b3032"><br></p>
  <h2 data-lake-id="suruX" id="suruX"><span data-lake-id="u51df18a6" id="u51df18a6">服务降级</span></h2>
  <p data-lake-id="uf5234b00" id="uf5234b00"><br></p>
  <p data-lake-id="u973f1f74" id="u973f1f74"><span data-lake-id="u1dd68abf" id="u1dd68abf">服务降级的概念听起来可能不是很容易理解，举一个生活中的例子就很好理解了。</span></p>
  <p data-lake-id="u585f9326" id="u585f9326"><br></p>
  <p data-lake-id="uabad652e" id="uabad652e"><span data-lake-id="ucbfcc227" id="ucbfcc227">有的时候我们去饭店吃饭，吃完饭以后服务员会拿一张问卷，让就餐者填写一下用户反馈。但是，这种让用户填写反馈的请求，只有在店里不忙的时候才会出现。如果店里非常忙，顾客很多的话，店员就不会再找就餐者填写问卷了。</span></p>
  <p data-lake-id="uacf1d0c2" id="uacf1d0c2"><br></p>
  <p data-lake-id="uc8dd9308" id="uc8dd9308"><span data-lake-id="u134e37a7" id="u134e37a7">其实，这种就是服务降级。在人流量大的时候，用户反馈这个功能就被降级了。因为他相对来说并没有那么重要。</span></p>
  <p data-lake-id="u3cd174dd" id="u3cd174dd"><br></p>
  <p data-lake-id="u6cf1084f" id="u6cf1084f"><span data-lake-id="ud752eac9" id="ud752eac9">接着再来看分布式系统的降级。</span></p>
  <p data-lake-id="u356fd33e" id="u356fd33e"><br></p>
  <p data-lake-id="uedb5d347" id="uedb5d347"><img src="http://www.hollischuang.com/wp-content/uploads/2018/11/15425244570790.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_34%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="ue6bfd991" id="ue6bfd991">​</span></p>
  <p data-lake-id="u09870868" id="u09870868"><br></p>
  <p data-lake-id="ubf165773" id="ubf165773"><span data-lake-id="ue4b74675" id="ue4b74675">上图是一张淘宝商品的详情页，对于很多剁手党来说这个页面真的是再熟悉不过了。</span></p>
  <p data-lake-id="ud648848c" id="ud648848c"><br></p>
  <p data-lake-id="u75801ca9" id="u75801ca9"><span data-lake-id="u7e442174" id="u7e442174">但是，这个页面我粗略的大致数了一下，至少有15个以上的功能模块，如：图片、标题、定价、库存、推荐、评价、物流、收藏、下单等。</span></p>
  <p data-lake-id="uc5cdee48" id="uc5cdee48"><br></p>
  <p data-lake-id="u42a957b6" id="u42a957b6"><span data-lake-id="u9800a2f6" id="u9800a2f6">虽然这些功能都展示在同一个页面上，但是其实这些功能并不都是在同一个应用里面的。这十几个模块可能分别在十几个应用中实现的。</span></p>
  <p data-lake-id="ue7e89104" id="ue7e89104"><br></p>
  <p data-lake-id="ua3ef61e5" id="ua3ef61e5"><span data-lake-id="u91caa185" id="u91caa185">详情页在渲染的时候，要和十几个应用进行网络交互。</span></p>
  <p data-lake-id="u4678f9e6" id="u4678f9e6"><br></p>
  <p data-lake-id="u82659b28" id="u82659b28"><span data-lake-id="uad54041c" id="uad54041c">这些功能中，有一些是非常重要的，比如：定价、库存、下单等。还有一些是相对来说没那么重要的，比如：推荐、收藏等。</span></p>
  <p data-lake-id="u5a5c225e" id="u5a5c225e"><br></p>
  <blockquote data-lake-id="u90d43c75" id="u90d43c75">
   <p data-lake-id="u0c11da07" id="u0c11da07"><span data-lake-id="u31689981" id="u31689981">这个识别哪些功能是核心功能、哪些功能是非核心功能，然后对非核心功能采取不同的降级方案制定的过程叫做</span><strong><span data-lake-id="ufe402378" id="ufe402378">降级预案</span></strong><span data-lake-id="u3f3dda03" id="u3f3dda03">。</span></p>
  </blockquote>
  <p data-lake-id="u3ce2a61e" id="u3ce2a61e"><br></p>
  <p data-lake-id="ubbdf6eab" id="ubbdf6eab"><span data-lake-id="u1f13c34d" id="u1f13c34d">双十一当天，整个网站的流量十分巨大的，详情页的访问量更是整个网站的重灾之地。所以，一旦有大促的时候，需要有限保证主要功能的可用，至于那些次要的功能就可以被降级掉，即不显示某些模块，或者返回一些默认内容。</span></p>
  <p data-lake-id="u31166d35" id="u31166d35"><br></p>
  <h2 data-lake-id="FdDwo" id="FdDwo"><span data-lake-id="u0dec708c" id="u0dec708c">降级的方式</span></h2>
  <p data-lake-id="u1a9d6a50" id="u1a9d6a50"><br></p>
  <p data-lake-id="ubf3ec8b3" id="ubf3ec8b3"><span data-lake-id="uaa3f56b8" id="uaa3f56b8">还拿之前的饭店中给用户做问卷调查的例子来说。当人流量大的时候，直接取消问卷调查只是一种方式。还有很多其他方式可以选择的。比如：</span></p>
  <p data-lake-id="u74039665" id="u74039665"><br></p>
  <p data-lake-id="u603cd8f5" id="u603cd8f5"><span data-lake-id="u95e1288b" id="u95e1288b">1、先让用户填写一下手机号，然后离店后，给用户发短信，让其填写电子问卷。</span></p>
  <p data-lake-id="u0d119e5e" id="u0d119e5e"><br></p>
  <p data-lake-id="ub2648781" id="ub2648781"><span data-lake-id="ua4dc2a22" id="ua4dc2a22">2、在店门口放一个问卷，用户离店时自己去填写问卷。 等等，只要愿意想，其实是有很多种方案的。</span></p>
  <p data-lake-id="u9ff9394d" id="u9ff9394d"><br></p>
  <p data-lake-id="u717e4cce" id="u717e4cce"><span data-lake-id="u96e7e474" id="u96e7e474">同样，对于大型网站来说，服务的降级其实也是有很多方式可以选的，常见的几种如下：</span></p>
  <p data-lake-id="uf4598f20" id="uf4598f20"><br></p>
  <h3 data-lake-id="QAmId" id="QAmId"><span data-lake-id="u84931653" id="u84931653">延迟服务</span></h3>
  <p data-lake-id="u2c1cbdad" id="u2c1cbdad"><br></p>
  <p data-lake-id="uf21268de" id="uf21268de"><span data-lake-id="u443ac7b8" id="u443ac7b8">比如发表了评论，重要服务，比如在文章中显示正常，但是延迟给用户增加积分，只是放到一个缓存中，等服务平稳之后再执行。</span></p>
  <p data-lake-id="u2173a184" id="u2173a184"><br></p>
  <h4 data-lake-id="YQPG2" id="YQPG2"><span data-lake-id="u4cd45c9c" id="u4cd45c9c">在粒度范围内关闭服务（片段降级或服务功能降级）</span></h4>
  <p data-lake-id="u9c8746b1" id="u9c8746b1"><br></p>
  <p data-lake-id="u2907474e" id="u2907474e"><span data-lake-id="udfd5e71a" id="udfd5e71a">比如关闭相关文章的推荐，直接关闭推荐区</span></p>
  <p data-lake-id="u43be848f" id="u43be848f"><br></p>
  <h4 data-lake-id="UQ9QX" id="UQ9QX"><span data-lake-id="u6db1c4dd" id="u6db1c4dd">页面异步请求降级</span></h4>
  <p data-lake-id="u7705ccc6" id="u7705ccc6"><br></p>
  <p data-lake-id="ufc90f819" id="ufc90f819"><span data-lake-id="u2092c5cc" id="u2092c5cc">比如商品详情页上有推荐信息/配送至等异步加载的请求，如果这些信息响应慢或者后端服务有问题，可以进行降级； </span><strong><span data-lake-id="u3c44bfbb" id="u3c44bfbb">页面跳转（页面降级）</span></strong></p>
  <p data-lake-id="u39ad1f76" id="u39ad1f76"><br></p>
  <p data-lake-id="u2c0ea72e" id="u2c0ea72e"><span data-lake-id="u231e051b" id="u231e051b">比如可以有相关文章推荐，但是更多的页面则直接跳转到某一个地址。</span></p>
  <p data-lake-id="ud8546bb2" id="ud8546bb2"><br></p>
  <h4 data-lake-id="qL3hA" id="qL3hA"><span data-lake-id="u6e5dfead" id="u6e5dfead">写降级</span></h4>
  <p data-lake-id="ud7509355" id="ud7509355"><br></p>
  <p data-lake-id="u425fe38a" id="u425fe38a"><span data-lake-id="ued4f6a46" id="ued4f6a46">比如秒杀抢购，我们可以只进行Cache的更新，然后异步同步扣减库存到DB，保证最终一致性即可，此时可以将DB降级为Cache。</span></p>
  <p data-lake-id="u7f83ad5a" id="u7f83ad5a"><br></p>
  <h4 data-lake-id="yAFyb" id="yAFyb"><span data-lake-id="u6aa73c96" id="u6aa73c96">读降级</span></h4>
  <p data-lake-id="u4e664911" id="u4e664911"><br></p>
  <p data-lake-id="u90977d6c" id="u90977d6c"><span data-lake-id="u2bb41f72" id="u2bb41f72">比如多级缓存模式，如果后端服务有问题，可以降级为只读缓存，这种方式适用于对读一致性要求不高的场景；</span></p>
  <p data-lake-id="u301c137b" id="u301c137b"><br></p>
  <blockquote data-lake-id="ucdb1f4d4" id="ucdb1f4d4">
   <p data-lake-id="ub0e35503" id="ub0e35503"><span data-lake-id="ue7db1334" id="ue7db1334">11月11日的零点到11月12日的零点之间无法退款，其实是采用了关闭服务这种降级方式</span></p>
  </blockquote>
  <h2 data-lake-id="fXXQQ" id="fXXQQ"><span data-lake-id="uaa9dc37d" id="uaa9dc37d">降级的介入方式</span></h2>
  <p data-lake-id="u67c78e55" id="u67c78e55"><br></p>
  <p data-lake-id="u79a5855e" id="u79a5855e"><span data-lake-id="uaa2814d6" id="uaa2814d6">按照是不是可以自动化降级，降级共有两种介入方式，分别是：</span><strong><span data-lake-id="udcc34a91" id="udcc34a91">自动开关降级</span></strong><span data-lake-id="ue00d8f32" id="ue00d8f32">和</span><strong><span data-lake-id="uc74fdd3f" id="uc74fdd3f">人工开关降级</span></strong><span data-lake-id="u3f2a48a8" id="u3f2a48a8">。</span></p>
  <p data-lake-id="ua475e71c" id="ua475e71c"><br></p>
  <h3 data-lake-id="vXB13" id="vXB13"><span data-lake-id="ue633fca3" id="ue633fca3">自动开关降级</span></h3>
  <p data-lake-id="uac1296c9" id="uac1296c9"><br></p>
  <p data-lake-id="ud6f99335" id="ud6f99335"><span data-lake-id="ua3a700b2" id="ua3a700b2">自动开关降级的方式一般是当系统达到某些设定的条件（系统负载、资源使用情况、SLA等指标）之后，自动执行一些策略。</span></p>
  <p data-lake-id="ue0444f4e" id="ue0444f4e"><br></p>
  <p data-lake-id="u13c4d02e" id="u13c4d02e"><span data-lake-id="u74732cb6" id="u74732cb6">常见的可以作为自动降级条件的指标有以下几个：</span></p>
  <p data-lake-id="u61c2f7fd" id="u61c2f7fd"><br></p>
  <h4 data-lake-id="hzWH3" id="hzWH3"><span data-lake-id="ueff2c715" id="ueff2c715">服务超时</span></h4>
  <p data-lake-id="udde52f6d" id="udde52f6d"><br></p>
  <p data-lake-id="u03bcce8d" id="u03bcce8d"><span data-lake-id="uff505f84" id="uff505f84">当访问的数据库/http服务/远程调用响应慢或者长时间响应慢，且该服务不是核心服务的话可以在超时后自动降级；</span></p>
  <p data-lake-id="u497a0665" id="u497a0665"><br></p>
  <p data-lake-id="u83aa3ea9" id="u83aa3ea9"><span data-lake-id="u29158b92" id="u29158b92">比如前面提到的详情页上有推荐和收藏功能，即使出现问题也不会影响用户的正常下单。如果是调用别人的远程服务，和对方定义一个服务响应最大时间，如果超时了则可以自动降级。</span></p>
  <p data-lake-id="u060fbdec" id="u060fbdec"><br></p>
  <h4 data-lake-id="slEOC" id="slEOC"><span data-lake-id="u6451920f" id="u6451920f">失败次数</span></h4>
  <p data-lake-id="u4bf1bb47" id="u4bf1bb47"><br></p>
  <p data-lake-id="u96dbc842" id="u96dbc842"><span data-lake-id="ud7e9f013" id="ud7e9f013">调用外部服务的时候，除了超时以外，最常见的异常情况就是调用失败。比如详情页中的库存信息，如果是某一次查询请求失败了，那么就可以通过读取缓存数据等方式直接降级掉。</span></p>
  <p data-lake-id="udf65fd14" id="udf65fd14"><br></p>
  <p data-lake-id="ucd3e0030" id="ucd3e0030"><span data-lake-id="u4471bcd8" id="u4471bcd8">但是，这种降级可能存在一个问题，就是虽然一次请求展示了缓存，但是其他用户访问的时候还是会查询库存信息，这对于库存系统来说就是雪上加霜。因为他可能已经有问题了，但是上游系统还是在不断的对他发送请求。</span></p>
  <p data-lake-id="u0fe0f22f" id="u0fe0f22f"><br></p>
  <p data-lake-id="u7fbabb87" id="u7fbabb87"><span data-lake-id="ue1024c84" id="ue1024c84">所以，可以针对这个查询库存的接口做统一的降级。设定一个失败次数的阈值，一旦整体失败次数达到这个阈值了，就对后续一段时间内的该查询接口做降级。直到其功能恢复。</span></p>
  <p data-lake-id="u2743cb5f" id="u2743cb5f"><br></p>
  <p data-lake-id="uae12dd31" id="uae12dd31"><strong><span data-lake-id="u93729b93" id="u93729b93">发生故障</span></strong></p>
  <p data-lake-id="u1474195d" id="u1474195d"><br></p>
  <p data-lake-id="ub2c15aa6" id="ub2c15aa6"><span data-lake-id="u585d95a8" id="u585d95a8">上面提到的失败可能是服务不稳定造成的，过一段时间可以自动恢复的。还有一种情况可能是依赖的服务彻底跪了、或者网络不通了等等。这种情况就可以直接降级了。</span></p>
  <p data-lake-id="u7f209606" id="u7f209606"><br></p>
  <p data-lake-id="u90d69290" id="u90d69290"><span data-lake-id="u8ee07d30" id="u8ee07d30">当HTTP请求返回固定的错误码、或者一个RPC请求的时候底层服务抛了异常以后，就认为有故障发生，对其进行降级即可。</span></p>
  <p data-lake-id="u24b28992" id="u24b28992"><br></p>
  <h4 data-lake-id="H9kJ1" id="H9kJ1"><span data-lake-id="uf6c0231f" id="uf6c0231f">限流降级</span></h4>
  <p data-lake-id="u3817aac3" id="u3817aac3"><br></p>
  <p data-lake-id="u8e858615" id="u8e858615"><span data-lake-id="uf0ae569b" id="uf0ae569b">还有种电商网站常见的策略，那就是限流降级。对于某些功能，设定一个流量阈值，一旦流量达到阈值的话，就进行降级。</span></p>
  <p data-lake-id="u0b4a71b7" id="u0b4a71b7"><br></p>
  <p data-lake-id="u79fe9d56" id="u79fe9d56"><span data-lake-id="u07af7c30" id="u07af7c30">比如秒杀功能，如果一瞬间流量太大，就可以进行限流降级。对于后续访问的用户直接提示已售空、跳转错误页、或者让他输入验证码重试等。</span></p>
  <p data-lake-id="ua17517a6" id="ua17517a6"><br></p>
  <h3 data-lake-id="UlBsx" id="UlBsx"><span data-lake-id="u7335726b" id="u7335726b">人工开关降级</span></h3>
  <p data-lake-id="u147655a9" id="u147655a9"><br></p>
  <p data-lake-id="u9b9f61cd" id="u9b9f61cd"><span data-lake-id="u081ac44e" id="u081ac44e">还有一种降级方式，那就是人工开关降级。</span></p>
  <p data-lake-id="u189c1f09" id="u189c1f09"><br></p>
  <p data-lake-id="u174bc642" id="u174bc642"><span data-lake-id="uad163d55" id="uad163d55">人工开关降级的方式是指当系统维护人员在发现系统异常之后，通过人工修改参数、关闭服务等方式进行降级的方法。</span></p>
  <p data-lake-id="u92cf130a" id="u92cf130a"><br></p>
  <p data-lake-id="u7293349f" id="u7293349f"><span data-lake-id="uff802142" id="uff802142">这种方式的好处是比较灵活，能够根据异常情况灵活应对；但弊端是对人的要求比较高，一来需要维护人员对系统有足够的了解，另外要求维护人员在系统异常时能够在第一时间进行处置。</span></p>
  <p data-lake-id="u63827bdc" id="u63827bdc"><br></p>
  <p data-lake-id="ufa186bbd" id="ufa186bbd"><span data-lake-id="u1a11bb61" id="u1a11bb61">还有一种情况，可能也会人工介入，那就是在大促之前，预估到流量会十分巨大，提早的识别出风险，为了节省资源保证主流程的可用，开发人员可以手动将某个功能降级掉。</span></p>
  <p data-lake-id="ueeb197a7" id="ueeb197a7"><br></p>
  <p data-lake-id="uc4e0988f" id="uc4e0988f"><span data-lake-id="u6d84ad34" id="u6d84ad34">这里说的人工开关降级，并不一定是一定要人工操作，也可能是人工通过一个定时任务进行定时触发的。</span></p>
  <p data-lake-id="uc52f963b" id="uc52f963b"><br></p>
  <p data-lake-id="u9bd2e578" id="u9bd2e578"><br></p>
  <h2 data-lake-id="vyNmd" id="vyNmd"><span data-lake-id="ud8860722" id="ud8860722">降级工具</span></h2>
  <p data-lake-id="u30b5b2d2" id="u30b5b2d2"><br></p>
  <p data-lake-id="ub746393b" id="ub746393b"><span data-lake-id="u8c3d5f0e" id="u8c3d5f0e">目前市面上，针对流量控制，限流降级主要有以下两种选择：Netflix Hystrix 和 Alibaba Sentinal。</span></p>
  <p data-lake-id="u28a1d5f1" id="u28a1d5f1"><br></p>
  <h3 data-lake-id="AfsPp" id="AfsPp"><span data-lake-id="u4fc38125" id="u4fc38125">Hystrix </span></h3>
  <p data-lake-id="u82b960f1" id="u82b960f1"><br></p>
  <p data-lake-id="u9c6bc419" id="u9c6bc419"><span data-lake-id="u6308cde5" id="u6308cde5">Hystrix是一个库，它提供了服务与服务之间的容错功能，主要体现在延迟容错和容错，从而做到控制分布式系统中的联动故障。Hystrix通过隔离服务的访问点，阻止联动故障，并提供故障的解决方案，从而提高了这个分布式系统的弹性。</span></p>
  <p data-lake-id="u082e1a0a" id="u082e1a0a"><br></p>
  <p data-lake-id="udee1bc9d" id="udee1bc9d"><span data-lake-id="u206ec807" id="u206ec807">Hystrix 的关注点在于以 隔离 和 熔断 为主的容错机制，超时或被熔断的调用将会快速失败，并可以提供 fallback 机制。</span></p>
  <p data-lake-id="ua381d551" id="ua381d551"><br></p>
  <h3 data-lake-id="LuZek" id="LuZek"><span data-lake-id="uc1ae30c8" id="uc1ae30c8">Sentinel </span></h3>
  <p data-lake-id="u48ef29ec" id="u48ef29ec"><br></p>
  <p data-lake-id="u8362830f" id="u8362830f"><span data-lake-id="u6911eded" id="u6911eded">Sentinel 是阿里中间件团队开源的，面向分布式服务架构的轻量级高可用流量控制组件，主要以流量为切入点，从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。</span></p>
  <p data-lake-id="u590f2734" id="u590f2734"><br></p>
  <p data-lake-id="ue82e23bb" id="ue82e23bb"><span data-lake-id="u5365707f" id="u5365707f">Sentinel 的侧重点在于：多样化的流量控制、熔断降级、系统负载保护、实时监控和控制台等</span></p>
  <p data-lake-id="udfb5b091" id="udfb5b091"><br></p>
  <h3 data-lake-id="PS6Ve" id="PS6Ve"><span data-lake-id="u58e55c1e" id="u58e55c1e">对比</span></h3>
  <p data-lake-id="u81441272" id="u81441272"><br></p>
  <p data-lake-id="uf7366867" id="uf7366867"><img src="http://www.hollischuang.com/wp-content/uploads/2018/11/15425290903028.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u0a3cf708" id="u0a3cf708">￼</span></p>
  <p data-lake-id="u6a68ad0c" id="u6a68ad0c"><br></p>
  <p data-lake-id="ud5a66507" id="ud5a66507"><span data-lake-id="uda2e3806" id="uda2e3806">上图是Sentinel的文档中，关于Sentinel-与-Hystrix-的对比。详情地址：</span><a href="https://github.com/alibaba/Sentinel/wiki/Sentinel-%E4%B8%8E-Hystrix-%E7%9A%84%E5%AF%B9%E6%AF%94" target="_blank" data-lake-id="ue3e3213c" id="ue3e3213c"><span data-lake-id="u00133224" id="u00133224">https://github.com/alibaba/Sentinel/wiki/Sentinel-与-Hystrix-的对比</span></a></p>
  <p data-lake-id="ua2c53641" id="ua2c53641"><br></p>
  <p data-lake-id="u850c525e" id="u850c525e"><span data-lake-id="u97bf81b5" id="u97bf81b5">​</span><br></p>
 </body>
</html>